/***************************************************************************************************
 *Copyright(C),2010-2016,Sumscope
 *FileName	:  JsonWideWriter.h
 *Author	:  scofined.qi
 *Version	:  1.0
 *Date		:  2016/09/12
 *Desc		:  //用于主要说明此程序文件完成的主要功能
 *Relation :
 *Others	:  //其他内容说明
 *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
 *History	:
 * //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
 ***************************************************************************************************/
#pragma once

#include <stdlib.h>
#include <string.h>

#include "../Utility.h"
#include "../core.h"
#include "../strings/simple_array.h"

namespace qb {
namespace base {
/*
        经过测试,性能是RapidJson生成性能的120%-333%,平均为244%

        Rapid json 生成范例:
        JsonParser doc(kObjectType);
        JsonValue record_array(kArrayType);

        obj.AddMember(JsonParser::StringRefType(""), *(bool*)(bin + offset),
   allocator); obj.AddMember(JsonParser::StringRefType(""),
   JsonParser::StringRefType((const char*)(bin + offset)), allocator);
        record_array.PushBack(jsrecord, doc.GetAllocator());
        doc.AddMember(JsonParser::StringRefType("records"), record_array,
   doc.GetAllocator()); JsonStringBuffer buffer; JsonWriter writer(buffer);
        doc.Accept(writer);
        records = G2W(buffer.GetString());
*/
class S_CORE_EXPORT JsonWideWriter {  // 将json转化为字符串
  typedef wchar_t Element;
  typedef JsonWideWriter Writer;
  typedef qb::base::SimpleArray<Element> Buffer;
  static const Element COMMA = L',';
  static const Element SEMICOLON = L':';
  static const Element LIST_START = L'[';
  static const Element LIST_END = L']';
  static const Element MAP_START = L'{';
  static const Element MAP_END = L'}';
  static const Element QUOTATION = L'"';
  bool m_finished;
  bool m_rootmap;
  bool m_rootlist;
  int m_count;  // 等级
  Buffer* m_buffer;

 public:
  class JsonWriterMap;
  class JsonWriterList {
    Writer* m_writer;
    int m_count;

   public:
    JsonWriterList(Writer* writer) : m_writer(writer), m_count(0) {}
    ~JsonWriterList() { End(); }
    void End() {
      if (m_writer) {
        if (m_count <= 0) m_writer->AddString(&LIST_START, 1);
        m_writer->AddString(&LIST_END, 1);
      }
      m_writer = 0;
    }
    Writer* AddMap() {
      AddHead();
      return m_writer;
    }
    Writer* AddList() {
      AddHead();
      return m_writer;
    }
    void AddString(const Element* str, int len = 0) {
      AddHead();
      m_writer->AddJsonString(str, len);
    }
    void AddBool(bool bvalue) {
      AddHead();
      m_writer->AddBool(bvalue);
    }
    void AddInt(int ivalue) {
      AddHead();
      m_writer->AddInt(ivalue);
    }
    void AddUint(unsigned int uvalue) {
      AddHead();
      m_writer->AddUint(uvalue);
    }
    void AddUint64(uint64_t u64) {
      AddHead();
      m_writer->AddUint64(u64);
    }
    void AddInt64(int64_t ivalue) {
      AddHead();
      m_writer->AddInt64(ivalue);
    }
    void AddDouble(double dvalue) {
      AddHead();
      m_writer->AddDouble(dvalue);
    }
    void AddHead() {
      m_writer->AddString(m_count <= 0 ? &LIST_START : &COMMA, 1);
      m_count++;
    }
  };
  class JsonWriterMap {
    Writer* m_writer;
    int m_count;

   public:
    JsonWriterMap(Writer* writer) : m_writer(writer), m_count(0) {}
    ~JsonWriterMap() { End(); }
    void End() {
      if (m_writer) {
        if (m_count <= 0) m_writer->AddString(&MAP_START, 1);
        m_writer->AddString(&MAP_END, 1);
      }
      m_writer = 0;
    }
    Writer* AddMap(const Element* name) {
      AddHead();
      m_writer->AddName(name, 0);
      m_writer->AddString(&SEMICOLON, 1);
      return m_writer;
    }
    Writer* AddList(const Element* name) {
      AddHead();
      m_writer->AddName(name, 0);
      m_writer->AddString(&SEMICOLON, 1);
      return m_writer;
    }
    void AddString(const Element* name, const Element* str, int len = 0) {
      AddHead();
      m_writer->AddName(name);
      m_writer->AddString(&SEMICOLON, 1);
      m_writer->AddJsonString(str, len);
    }
    void AddBool(const Element* name, bool bvalue) {
      AddHead();
      m_writer->AddName(name);
      m_writer->AddString(&SEMICOLON, 1);
      m_writer->AddBool(bvalue);
    }
    void AddInt(const Element* name, int ivalue) {
      AddHead();
      m_writer->AddName(name);
      m_writer->AddString(&SEMICOLON, 1);
      m_writer->AddInt(ivalue);
    }
    void AddUint(const Element* name, unsigned int uvalue) {
      AddHead();
      m_writer->AddName(name);
      m_writer->AddString(&SEMICOLON, 1);
      m_writer->AddUint(uvalue);
    }
    void AddUint64(const Element* name, uint64_t u64) {
      AddHead();
      m_writer->AddName(name);
      m_writer->AddString(&SEMICOLON, 1);
      m_writer->AddUint64(u64);
    }
    void AddInt64(const Element* name, int64_t ivalue) {
      AddHead();
      m_writer->AddName(name);
      m_writer->AddString(&SEMICOLON, 1);
      m_writer->AddInt64(ivalue);
    }
    void AddDouble(const Element* name, double dvalue) {
      AddHead();
      m_writer->AddName(name);
      m_writer->AddString(&SEMICOLON, 1);
      m_writer->AddDouble(dvalue);
    }
    void AddHead() {
      m_writer->AddString(m_count <= 0 ? &MAP_START : &COMMA, 1);
      m_count++;
    }
  };

 public:
  typedef JsonWriterList List;
  typedef JsonWriterMap Map;
  JsonWideWriter(int initCapcity = 0);
  ~JsonWideWriter();
  int GetCapcity() const;
  void Start(int capcity);
  const Element* c_str();
  int size();

  Writer* AddRootList() {
    m_rootlist = true;
    m_rootmap = false;
    return this;
  }
  Writer* AddRootMap() {
    m_rootmap = true;
    m_rootlist = false;
    return this;
  }
  Writer* AddMap(const Element* name) {
    if (m_count > 0) AddString(&COMMA, 1);
    AddName(name, 0);
    AddString(&SEMICOLON, 1);
    m_count++;
    return this;
  }
  Writer* AddList(const Element* name) {
    if (m_count > 0) AddString(&COMMA, 1);
    AddName(name, 0);
    AddString(&SEMICOLON, 1);
    m_count++;
    return this;
  }

 protected:
  void AddName(const Element* name, int len = 0) {
    AddString(&QUOTATION, 1);
    AddString(name, len);
    AddString(&QUOTATION, 1);
  }
  void AddJsonString(const Element* str, int len = 0);
  void AddString(const Element* str, int len = 0);
  void AddBool(bool bvalue) {
    AddString(bvalue ? L"true" : L"false", bvalue ? 4 : 5);
  }
  void AddInt(int ivalue) {
    Element buf[64] = {0};
#if WIN32
    _itow_s(ivalue, buf, 64, 10);
#else
    swprintf(buf, 60, L"%d", ivalue);
#endif
    AddString(buf);
  }
  void AddUint(unsigned int uvalue) {
    Element buf[64] = {0};
    int len = FMTBUFW(buf, L"%u", uvalue);
    AddString(buf, len);
  }
  void AddUint64(uint64_t u64) {
    Element buf[64] = {0};
#if WIN32
    _ui64tow_s(u64, buf, 64, 10);
#else
    swprintf(buf, 64, L"%llu", u64);  // TODO: 64?
#endif
    AddString(buf);
  }
  void AddInt64(int64_t ivalue) {
    Element buf[64] = {0};
#if WIN32
    _i64tow_s(ivalue, buf, 64, 10);
#else
    swprintf(buf, 64, L"%lld", ivalue);
#endif
    AddString(buf);
  }
  void AddDouble(double dvalue) {
    Element buf[64] = {0};
    int len = FMTBUFW(buf, L"%f", dvalue);
    AddString(buf, len);
  }
};
}  // namespace base
}  // namespace qb
